import java.net.Socket; 
import java.net.ServerSocket; 
import java.net.InetAddress;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.util.Vector;
import java.util.Stack;

/**
Server-program
*/
public class Server {
	private static int connectionPort = 8989;
	private static Vector<Listener> listeners = new Vector<Listener>();
	private static Object lock = new Object();
	private static ServerSocket serverSocket = null;
	
	
	public static void main(String[] args) throws IOException {       
        boolean listening = true;
        
	/**
	Try/catch for starting the server, over the port 8989
	*/
		try {
			serverSocket = new ServerSocket(connectionPort); 
		} catch (IOException e){
		//it failed
			System.err.println("Could not listen on port: " + connectionPort);
			System.exit(1);
		}
		//it succeded
		System.out.println("Server started listening on port: " + connectionPort);
	
		Listener listener;
		long counter = 0; //counter, so we get a nice unique id to each thread
		while(true){		
			try {
				(listener = new Listener(serverSocket.accept(), counter++)).start(); //create a listener and gives it a new socket
				synchronized(lock){
					listeners.add(listener); //add the new listener to list
				}
				Thread.currentThread().yield();
			}catch (IOException e) {
				System.err.println("Error " + e);
				System.exit(1);
			}
		}
	}

	/**
	The thread that control the sockets for each client.
	*/
	private static class Listener extends Thread {
		public Socket socket;
		InetAddress	ip;
		long id;
		PrintWriter out = null;
        BufferedReader in = null;
		boolean off;
		
		public Listener(Socket socket, long id){
			this.socket = socket;
			this.ip = socket.getInetAddress();
			this.id = id;
			this.off = false;
			
			try {
				out = new PrintWriter(socket.getOutputStream(), true); //create a printwriter that allows the thread to send data to its client
				in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //create a bufferedreader allowing the thread to read data from client
			} catch (IOException e) {
				System.err.println("Error " + e);
				System.exit(1);
			}
		}
		
		public void run() {
			String msg;
			try {
				while(true){
				msg = in.readLine(); //reads a line, otherwise it waits for a read
					if(msg.matches("(\\s*\\S+\\s*)+")){ //removes lines that only contain whitespaces
						System.out.println(ip+";"+id+": "+msg);
						synchronized(lock){ //lock the list of sockets to clients
							for(int i = 0; i < listeners.size(); ++i){ //lets go and send it to every client
								if(listeners.get(i).off){ //this client is marked for deletion
									listeners.remove(i); //now we can remove old client that has disconnected
									--i;
								}else
									if(listeners.get(i).id != this.id) //check to see so it does not send message back
										listeners.get(i).out.println(msg); //send message to clients
							}
						}
					}
					Thread.currentThread().yield();
				}
			} catch (IOException e) {
				System.err.println("Child #"+id+" died");
				this.off = true; //this thread is now not doing anything, mark objekt for deletion.				
			}
		}
	}	
}